package com.xyx.yfy_site_msg.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyx.yfy_site_msg.system.entity.YfyFile;
import com.xyx.yfy_site_msg.system.entity.YfyUser;
import com.xyx.yfy_site_msg.system.service.YfyFileService;
import com.xyx.yfy_site_msg.system.utils.DataGridView;
import com.xyx.yfy_site_msg.system.utils.ResultObj;
import com.xyx.yfy_site_msg.system.utils.WebUtils;
import com.xyx.yfy_site_msg.system.vo.YfyFileVo;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Controller
@RequestMapping("/upload")
public class YfyUploadController {

    @Autowired
    private YfyFileService yfyFileService;

    // 设置固定的日期格式
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
    SimpleDateFormat sdfs = new SimpleDateFormat("yyyy-MM-dd");

    public static String filePath = "E:/upload/";
    public static Integer STATUS_TRUE = 1;
    public static Integer STATUS_FALSE = 0;

    // 日志打印
    private Logger log = LoggerFactory.getLogger("YfyUploadController");

    // 上传接口
    @ResponseBody
    @RequestMapping("uploadFile")
    public ResultObj fileUploads(HttpServletRequest request, @RequestParam("file") MultipartFile file) throws IOException {
        // 得到格式化后的日期
        String format = sdf.format(new Date());
        // 获取上传的文件名称
        String fileName = file.getOriginalFilename();
        // 时间 和 日期拼接
        String newFileName = format + "_" + fileName;
        // 得到文件保存的位置以及新文件名
        File dest = new File(filePath + newFileName);

        // 将上传文件相关信息存入实体类中
        YfyFileVo fileVo = new YfyFileVo();
        fileVo.setOldFileName(fileName);
        fileVo.setNewFileName(newFileName);
        fileVo.setUploadTime(new Date());
        YfyUser user = (YfyUser) WebUtils.getSession().getAttribute("user");
        fileVo.setUploadUser(user.getUsername());
        fileVo.setPath(filePath + newFileName);
        fileVo.setStatus(STATUS_TRUE);
        try {
            // 上传的文件被保存了
            file.transferTo(dest);
            // 打印日志
            log.info("上传成功，当前上传的文件保存在{}", filePath + newFileName);
            this.yfyFileService.save(fileVo);
        } catch (IOException e) {
            log.error(e.toString());
            return ResultObj.UPLOAD_ERROR;
        }
        return ResultObj.UPLOAD_SUCCESS;
    }

    /**
     * 分页查询文件信息
     *
     * @param yfyFileVo
     * @return
     */
    @ResponseBody
    @GetMapping("queryFileForPage")
    public DataGridView queryFileForPage(YfyFileVo yfyFileVo) {
        // 执行分页查询文件信息
        Page<YfyFile> page = new Page<>(yfyFileVo.getPage(), yfyFileVo.getLimit());
        QueryWrapper<YfyFile> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(yfyFileVo.getNewFileName()), "new_file_name", yfyFileVo.getNewFileName());
        queryWrapper.like(StringUtils.isNotBlank(yfyFileVo.getUploadUser()), "upload_user", yfyFileVo.getUploadUser());
        queryWrapper.orderByDesc("id");
        this.yfyFileService.page(page, queryWrapper);
        return new DataGridView(page.getTotal(), page.getRecords());
    }

    /**
     * 更新文件状态【根据数据库中存在的数据去查询本地文件夹，来判断是否存在该文件，如果不存在，则更新数据库中文件状态--目的是数据库和服务器存储的文件情况保持一致】
     *
     * @return
     */
    @ResponseBody
    @RequestMapping("updateFileStatus")
    public ResultObj updateFileStatus() {
        List<YfyFile> list = this.yfyFileService.list();
        for (int i = 0; i < list.size(); i++) {
            String path = list.get(i).getPath();
            try {
                File file = new File(path);
                QueryWrapper<YfyFile> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("path", path);
                YfyFile one = this.yfyFileService.getOne(queryWrapper);
                if (!file.exists()) {
                    one.setStatus(STATUS_FALSE);
                } else {
                    one.setStatus(STATUS_TRUE);
                }
                this.yfyFileService.updateById(one);
            } catch (Exception e) {
                e.printStackTrace();
                return ResultObj.UPDATE_ERROR;
            }
        }
        return ResultObj.UPDATE_SUCCESS;
    }

    /**
     * 文件下载
     *
     * @param fileName
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("downloadFile")
    public ResponseEntity<Object> downloadFile(String fileName, HttpServletResponse response) throws IOException {
        return downloadFile(response, fileName);
    }

    /**
     * 文件下载【静态方法】
     *
     * @param response
     * @param fileName
     * @return
     */
    public static ResponseEntity<Object> downloadFile(HttpServletResponse response, String fileName) throws IOException {
        // 获取当前操作系统桌面路径，下载的文件将被直接下载到桌面上
        String systemPath = String.valueOf(FileSystemView.getFileSystemView().getHomeDirectory().getAbsoluteFile());
        File file = new File(filePath, fileName);
        if (file.exists()) {
            try {
                byte[] bytes = FileUtils.readFileToByteArray(file);
                String out = systemPath + "\\" + fileName;
                FileInputStream fileInputStream = new FileInputStream(file);
                FileOutputStream fileOutputStream = new FileOutputStream(out);
                BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                int len = 0;
                while ((len = bufferedInputStream.read(bytes)) != -1) {
                    bufferedOutputStream.write(bytes);
                }
                bufferedInputStream.close();
                bufferedOutputStream.close();
                HttpHeaders headers = new HttpHeaders();
                // 封装响应内容类型(APPLICATION_OCTET_STREAM 响应的内容不限定)
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                ResponseEntity<Object> entity = new ResponseEntity<>(bytes, headers, HttpStatus.CREATED);
                return entity;
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            return null;
        } else {
            PrintWriter out;
            out = response.getWriter();
            out.write("文件不存在");
            out.flush();
            out.close();
        }
        return null;
    }

    /**
     * 文件删除
     * -先根据文件路径删除文件后，再删除数据库中记录
     *
     * @return
     */
    @ResponseBody
    @RequestMapping("deleteFile")
    public ResultObj deleteFile(String path) {
        try {
            removeFileByPath(path);
            QueryWrapper<YfyFile> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("path", path);
            this.yfyFileService.remove(queryWrapper);
            return ResultObj.DELETE_SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            return ResultObj.DELETE_ERROR;
        }
    }

    /**
     * 文件删除【静态方法】
     */
    public static void removeFileByPath(String path) {
        try {
            URLEncoder.encode(path, "UTF-8");// 处理路径中的中文编码
            File file = new File(path);
            file.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
